package com.schoolegard.services.impl;

import java.io.StringWriter;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.axis2.AxisFault;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import com.schoolegard.services.MessageSendService;
import com.schoolegard.services.SchoolDataService;
import com.schoolgard.dao.AlarmLogDao;
import com.schoolgard.dao.MessageSendLogDao;
import com.schoolgard.dao.MessageStrategyDao;
import com.schoolgard.dao.MessageTaskPoolDao;
import com.schoolgard.entitybean.AlarmClass;
import com.schoolgard.entitybean.AlarmLog;
import com.schoolgard.entitybean.MessageSendLog;
import com.schoolgard.entitybean.MessageStrategy;
import com.schoolgard.entitybean.MessageTaskPool;
import com.schoolgard.entitybean.MsgReceiver;
import com.supersystem.utils.DateUtil;
import com.tecsun.business.sms.manage.interfaces.GetSMSConfig;
import com.tecsun.business.sms.manage.interfaces.GetSMSConfigResponse;
import com.tecsun.business.sms.manage.interfaces.SMSConfigInterface;
import com.tecsun.business.sms.manage.interfaces.SMSConfigInterfaceStub;
import com.tecsun.business.sms.manage.interfaces.bean.config.ArrayOfSMSConfig;
import com.tecsun.business.sms.manage.interfaces.bean.config.SMSConfig;
import com.tecsun.business.sms.manage.interfaces.bean.config.SMSConfigBean;
import com.tecsun.business.sms.manage.interfaces.bean.config.SMSConfigBeanResponse;
import com.tecsun.business.sms.message.interfaces.CustomSMS;
import com.tecsun.business.sms.message.interfaces.CustomSMSResponse;
import com.tecsun.business.sms.message.interfaces.SendSMSInterface;
import com.tecsun.business.sms.message.interfaces.SendSMSInterfaceStub;
import com.tecsun.business.sms.message.interfaces.bean.send.ArrayOfCustom;
import com.tecsun.business.sms.message.interfaces.bean.send.Custom;
import com.tecsun.business.sms.message.interfaces.bean.send.CustomSMSBean;

public class MessageSendServiceImpl implements MessageSendService {
	
	private AlarmLogDao alarmLogDao;
	
	private MessageStrategyDao strategyDao;

	private SchoolDataService schoolDataService;
	
	private MessageSendLogDao messageSendLogDao;
	
	private MessageTaskPoolDao messageTaskPoolDao;
	
	public Date send(Date startTime) {
		try{
		if(startTime == null) {
			return null;
		}
		int configId = getConfigId();
		if(configId == 0) {
			System.out.println("CAN NOT GET CONFIGID");
			return null;
		}
		List<AlarmLog> alarmList = findRightAlarmLog(findAlarmLog(startTime));
		if(alarmList == null || alarmList.size() == 0) {
			return null;
		}
		List<MessageTaskPool> tasks = getMessageTask(alarmList);
		if(tasks == null || tasks.size() == 0) {
			return null;
		}
		//保存发送日志
		saveSendLog(tasks);
		//保存需要重复发送短信的任务
		saveSendTask(tasks);
		//组装发送短信bean
		List<Custom> customs = getSMSBen(tasks,configId);
		sendWork(customs);
		return alarmList.get(0).getDatetime();
		}catch(Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	private void sendWork(List<Custom> customs){
		CustomSMSBean bean = new CustomSMSBean();
		ArrayOfCustom arrayOfCustom = new ArrayOfCustom();
		arrayOfCustom.setCustom(customs.toArray(new Custom[0]));
		bean.setSms(arrayOfCustom);
		CustomSMS customSMS = new CustomSMS();
		customSMS.setIn0(bean);
		SendSMSInterface sendSMSInterface;
		try {
			sendSMSInterface = new SendSMSInterfaceStub();
			CustomSMSResponse response = sendSMSInterface.customSMS(customSMS);
			System.out.println("message send result："+response.getOut().getStatus());
		} catch (AxisFault e) {
			e.printStackTrace();
		} catch (RemoteException e) {
			e.printStackTrace();
		}
		
	}
	
	private void saveSendLog(List<MessageTaskPool> tasks){
		for(MessageTaskPool task : tasks) {
			MessageSendLog sendLog = new MessageSendLog();
			sendLog.setAlarmInfo(task.getAlarmInfo());
			sendLog.setAlarmLevel(task.getAlarmLevel());
			sendLog.setAlarmTime(task.getAlarmTime());
			sendLog.setAlarmType(task.getAlarmType());
			sendLog.setDeviceGuid(task.getDeviceGuid());
			sendLog.setReceivers(task.getReceivers());
			sendLog.setSchoolName(task.getSchoolName());
			sendLog.setSendTime(new Date());
			messageSendLogDao.create(sendLog);
		}
		
	}
	
	private void saveSendTask(List<MessageTaskPool> tasks){
		for(MessageTaskPool task : tasks) {
			if(task.getResendTimes() > 1) {
				messageTaskPoolDao.create(task);
			}
		}
	}
	
	private List<Custom> getSMSBen(List<MessageTaskPool> tasks,int configId){
		List<Custom> smsbeans = new ArrayList<Custom>();
		for(MessageTaskPool task : tasks) {
			Custom sms = new Custom();
			sms.setConfigid(configId);
			sms.setCustomtype(1);
			sms.setMessage(task.getAlarmInfo());
			String receivers = task.getReceivers();
			sms.setMobile(receivers);
			smsbeans.add(sms);
		}
		return smsbeans;
	}
	
	private int getConfigId(){
		SMSConfigBean param = new SMSConfigBean();
		param.setAuthkey("123456");
		GetSMSConfig smsConfig = new GetSMSConfig();
		smsConfig.setIn0(param);
		SMSConfigInterface configInterface;
		try {
			configInterface = new SMSConfigInterfaceStub();
			GetSMSConfigResponse response = configInterface.getSMSConfig(smsConfig);
			if(response != null) {
				SMSConfigBeanResponse beanResponse = response.getOut();
				if(beanResponse != null) {
					ArrayOfSMSConfig configs = beanResponse.getConfig();
					if(configs != null){
						SMSConfig[] config = configs.getSMSConfig();
						if(config != null && config.length > 0) {
							return config[0].getConfigid();
						}
					}
				}
			}
		} catch (AxisFault e) {
			e.printStackTrace();
			return 0;
		} catch (RemoteException e) {
			e.printStackTrace();
			return 0;
		} catch (Exception e){
			e.printStackTrace();
			return 0;
		}
		return 0;
	}
	
	private List<AlarmLog> findAlarmLog(Date startTime) throws Exception{
		DetachedCriteria criteria = DetachedCriteria.forClass(AlarmLog.class);
		if(startTime == null) {
			return null;
		}
		criteria.add(Restrictions.gt("datetime", startTime));
		criteria.add(Restrictions.eq("status", "1"));
		criteria.addOrder(Order.desc("id"));
		return alarmLogDao.findByCriteria(criteria);
	}

	private List<AlarmLog> findRightAlarmLog(List<AlarmLog> oldList) throws Exception{
		if(oldList == null) {
			return new ArrayList<AlarmLog>();
		}
		List<AlarmLog> newList = new ArrayList<AlarmLog>();
		for(AlarmLog oldLog : oldList){
			if(noEqualsList(oldLog,newList)){
				newList.add(oldLog);
			}
		}
		return newList;
	}
	
	private boolean noEqualsList(AlarmLog oldLog , List<AlarmLog> newList){
		for(AlarmLog newLog : newList) {
			if(alarmLogEquals(newLog,oldLog)){
				return false;
			}
		}
		return true;
	}
	
	private boolean alarmLogEquals(AlarmLog log1, AlarmLog log2){
		if(!log1.getAlarmClass().equals(log2.getAlarmClass())){
			return false;
		}
		if(!log1.getContent().equals(log2.getContent())){
			return false;
		}
		if(!log1.getDevice().equals(log2.getDevice())){
			return false;
		}
		return true;
	}

	private List<MessageTaskPool> getMessageTask(List<AlarmLog> alarmLogs){
		List<MessageTaskPool> tasks = new ArrayList<MessageTaskPool>();
		for(AlarmLog alarmlog : alarmLogs){
			MessageStrategy strategy = findStrategy(alarmlog);
			if(strategy == null) {
				continue;
			}
			//判断该告警信息是否已经在发送短信任务中
			if(alarmLogIsInTask(alarmlog)) {
				continue;
			}
			//判断告警是否是新的告警，如果是已经发送过短信，则不发重复发送。
			if(isNotNewAlarmLog(alarmlog)){
				continue;
			}
			MessageTaskPool task = new MessageTaskPool();
			task.setAlarmInfo(alarmlog.getContent());
			task.setAlarmLevel(alarmlog.getAlarmClass().getLevel());
			task.setAlarmTime(alarmlog.getDatetime());
			task.setAlarmType(alarmlog.getAlarmClass().getType().toString());
			task.setDeviceGuid(alarmlog.getDevice().getGuid());
			task.setNextSendTime(DateUtil.getPlusDateOfMinute(new Date(), strategy.getResendInterval()));
			Long schoolId = null;
			try{
				schoolId = alarmlog.getDevice().getOrganization().getSchoolId();
			}catch(Exception e){
				e.printStackTrace();
				schoolId = null;
			}
			if(schoolId != null && schoolId > 0) {
				List<MsgReceiver> receiverList = schoolDataService.findReceiverListBySchoolId(schoolId);
				StringWriter sw = new StringWriter();
				for(MsgReceiver receiver : receiverList){
					sw.append(receiver.getPhone());
				}
				task.setReceivers(sw.toString());
			}else{
				continue;
			}
			
			task.setResendInterval(strategy.getResendInterval());
			task.setResendTimes(strategy.getResendTimes());
			task.setSchoolName(alarmlog.getDevice().getOrganization().getName());
			task.setSendType(strategy.getSendType());
			tasks.add(task);
		}
		return tasks;
	}
	
	private boolean alarmLogIsInTask(AlarmLog alarmlog){
		DetachedCriteria criteria = DetachedCriteria.forClass(MessageTaskPool.class);
		criteria.add(Restrictions.eq("deviceGuid", alarmlog.getDevice().getGuid()));
		criteria.add(Restrictions.eq("alarmLevel", alarmlog.getAlarmClass().getLevel()));
		criteria.add(Restrictions.eq("alarmType", alarmlog.getAlarmClass().getType()));
		criteria.add(Restrictions.eq("alarmInfo", alarmlog.getContent()));
		int count = messageTaskPoolDao.getRowCount(criteria);
		if(count > 0) {
			return true;
		}
		return false;
	}
	
	private boolean isNotNewAlarmLog(AlarmLog alarmlog){
		DetachedCriteria criteria = DetachedCriteria.forClass(MessageSendLog.class);
		criteria.add(Restrictions.eq("deviceGuid", alarmlog.getDevice().getGuid()));
		criteria.add(Restrictions.eq("alarmLevel", alarmlog.getAlarmClass().getLevel()));
		criteria.add(Restrictions.eq("alarmType", alarmlog.getAlarmClass().getType()));
		criteria.add(Restrictions.eq("alarmInfo", alarmlog.getContent()));
		criteria.add(Restrictions.ge("alarmTime", DateUtil.getDateAfterDays(new Date(), -1)));
		criteria.addOrder(Order.desc("id"));
		List<MessageSendLog> sendlogs = messageSendLogDao.findByCriteria(criteria, 0, 1);
		if(sendlogs == null || sendlogs.size() == 0) {
			return false;
		}
		MessageSendLog sendlog = sendlogs.get(0);
		AlarmLog log = getPreLog(alarmlog);
		if(log == null) {
			return true;
		}
		if(DateUtil.dateEqual(sendlog.getAlarmTime(), log.getDatetime()) > 0) {
			return true;
		}
		return false;
	}
	
	/**
	 * 获取相同告警信息最近一次处理的告警时间
	 * @param alarmlog
	 * @return
	 */
	private AlarmLog getPreLog(AlarmLog alarmlog){
		DetachedCriteria criteria = DetachedCriteria.forClass(AlarmLog.class);
		criteria.add(Restrictions.eq("alarmClass", alarmlog.getAlarmClass()));
		criteria.add(Restrictions.eq("device", alarmlog.getDevice()));
		criteria.add(Restrictions.eq("content", alarmlog.getContent()));
		criteria.add(Restrictions.ne("status", alarmlog.getStatus()));
		criteria.add(Restrictions.ge("alarmLogDao", DateUtil.getDateAfterDays(new Date(), -1)));
		criteria.addOrder(Order.desc("id"));
		List<AlarmLog> logs = alarmLogDao.findByCriteria(criteria, 0, 1);
		if(logs == null || logs.size() == 0 ) {
			return null;
		}
		return logs.get(0);
		
	}
	
	private MessageStrategy findStrategy(AlarmLog alarmlog){
		DetachedCriteria criteria = DetachedCriteria.forClass(MessageStrategy.class);
		AlarmClass alarmClass = alarmlog.getAlarmClass();
		if(alarmClass != null) {
			criteria.add(Restrictions.eq("alarmLevel", alarmClass.getLevel()));
			criteria.add(Restrictions.eq("alarmTypeId", alarmClass.getType()));
		}else{
			return null;
		}
		List<MessageStrategy> strategyList = strategyDao.findByCriteria(criteria);
		if(strategyList != null && strategyList.size() > 0) {
			return strategyList.get(0);
		}
		return null;
	}

	public void setAlarmLogDao(AlarmLogDao alarmLogDao) {
		this.alarmLogDao = alarmLogDao;
	}

	public void setStrategyDao(MessageStrategyDao strategyDao) {
		this.strategyDao = strategyDao;
	}

	public void setSchoolDataService(SchoolDataService schoolDataService) {
		this.schoolDataService = schoolDataService;
	}

	public void setMessageSendLogDao(MessageSendLogDao messageSendLogDao) {
		this.messageSendLogDao = messageSendLogDao;
	}

	public void setMessageTaskPoolDao(MessageTaskPoolDao messageTaskPoolDao) {
		this.messageTaskPoolDao = messageTaskPoolDao;
	}
}
